/* 
 * File:   StorageRuleContainer.h
 * Author: jeffrey
 *
 * Created on May 19, 2010, 10:02 PM
 */

#ifndef _STORAGERULECONTAINER_H
#define	_STORAGERULECONTAINER_H
#include "StorageRule.h"
#include <vector>

using namespace std;

class StorageRuleContainer {
public:
    StorageRuleContainer();
    StorageRuleContainer(const StorageRuleContainer& orig);
    virtual ~StorageRuleContainer();
    void print();
    void buildFile(string filename);
    void addStructure(string struc);
    void loadStructure(string struc);
    void addPStatement(string struc, string psql);
    void modifyStructure(string struc, int entryNo);
    void deleteStructure(string struc, int entryNo);
    void printSRULElist();
    void printSRULElist(string struc);
    string getSRULEid(int entryNo);

    //Procedures for SQL generator
    vector<DMLStatement> getSQL(string structure);

    //vector<string>& getReferences();


private:
    map<string, StorageRule> storagerulecontainer;

};

StorageRuleContainer::StorageRuleContainer() {
}

StorageRuleContainer::StorageRuleContainer(const StorageRuleContainer& orig) {
    storagerulecontainer = orig.storagerulecontainer;
}

StorageRuleContainer::~StorageRuleContainer() {
}

void StorageRuleContainer::addStructure(string struc) {
    //TO-DO: check STRUCTURE for errors from MAP.addStructure
    Derivation d;
    d.addDerivString(struc);
    StorageRule s;
    s.setTerminalDerivation(d);
    storagerulecontainer.insert(pair<string, StorageRule > (s.getId(), s));
}

void StorageRuleContainer::loadStructure(string struc) {
    //TO-DO: check STRUCTURE for errors from MAP.addStructure
    Derivation d;

    d.addDerivString(struc);

    StorageRule s;
    s.loadTerminalDerivation(d);

    storagerulecontainer.insert(pair<string, StorageRule > (s.getId(), s));
}

void StorageRuleContainer::addPStatement(string struc, string psql) {
    if (storagerulecontainer.find(struc) != storagerulecontainer.end()) {
        StorageRule& s = storagerulecontainer[struc];
        s.addPSQL(psql);
        storagerulecontainer[struc] = s;
    }
}

void StorageRuleContainer::print() {
    cout << ".SRULE" << "\n";
    multimap<string, StorageRule>::iterator it;
    for (it = storagerulecontainer.begin(); it != storagerulecontainer.end();
            ++it) {
        StorageRule& d = (*it).second;
        d.print();
    }
    cout << ".END_SRULE" << "\n\n";
}

void StorageRuleContainer::buildFile(string filename) {
    ofstream myfile(filename.c_str(), ios::app);
    myfile << ".SRULE" << "\n\n";
    map<string, StorageRule>::iterator it;
    myfile.close();
    for (it = storagerulecontainer.begin(); it != storagerulecontainer.end();
            ++it) {
        StorageRule& d = (*it).second;

        d.buildFile(filename);
    }
    myfile.open(filename.c_str(), ios::app);
    myfile << ".END_SRULE" << "\n\n";
}

void StorageRuleContainer::printSRULElist() {
    int i;
    i = 1;
    map<string, StorageRule>::iterator it;
    for (it = storagerulecontainer.begin(); it != storagerulecontainer.end();
            ++it) {
        cout << i << ") " << (*it).first << endl;
        i++;
    }
}

void StorageRuleContainer::printSRULElist(string struc) {

    map<string, StorageRule>::iterator it;
    it = storagerulecontainer.find(struc);
    if (it != storagerulecontainer.end())
        (*it).second.print();

}

//TODO: Remove stupid, use iteretor instead

string StorageRuleContainer::getSRULEid(int entryNo) {
    int i;
    i = 1;
    map<string, StorageRule>::iterator it;
    for (it = storagerulecontainer.begin(); it != storagerulecontainer.end();
            ++it) {
        if (i == entryNo) {
            string s;
            s = (*it).first;
            cout << s << endl;
            return s;
        }
        i++;
    }
}

vector<DMLStatement> StorageRuleContainer::getSQL(string structure) {
    map<string, StorageRule>::iterator it;
    it = storagerulecontainer.find(structure);
    if (it == storagerulecontainer.end()) {
        //Return an empty vector of DML statements if not found
        vector<DMLStatement> ret;
        return ret;
    }
   
    return (*it).second.getSQL();
}
#endif	/* _STORAGERULECONTAINER_H */

